﻿//-----------------------------------------------------------------------
// <copyright file="ObjectValidation">
//     根据实体类属性标签校验实体类对象
//     Company copyright tag.
// </copyright>
//-----------------------------------------------------------------------
namespace WLFramework.Validation
{
    using System;
    using System.Linq.Expressions;
    using WLFramework.Reflection.Metadata;
    using WLFramework.Web.Binder;

    public class ObjectValidation
    {
        #region Static Method
        public static bool IsValid<T>(T input, out ModelExceptionCollection errors)
            where T : class 
        {
            return IsValid(input, typeof(T), out errors);
        }

        public static bool IsValid(object input, Type type, out ModelExceptionCollection errors)
        {
            Shield.AssertNotNull(ref input, "name");
            Shield.AssertNotNull(ref type, "type");
            Shield.AssertIsTrue(type.IsInstanceOfType(input));

            errors = new ModelExceptionCollection();

            IModelMetadataProvider provider = new ModelMetadataProvider();
            ModelMetadata metadata = new ModelMetadata(provider, type);
            bool flag = true;

            foreach (var member in metadata.Members)
            {
                ValidateContext context = new ValidateContext(metadata, member);

                try
                {
                    object value = member.Getter.Getter(input);
                    
                    if (member.Required != null)
                    {
                        var result = member.Required.IsValid(value, context);
                        if (result != ValidateResult.Success)
                        {
                            // 当前属性不允许为空
                            errors[member.MemberName] = CreateException(metadata, member, result.ErrorMessage);
                            flag = false;
                            continue;
                        }
                    }

                    if (value != null || value != DBNull.Value)
                    {
                        foreach (var valid in member.Validations)
                        {
                            // 验证其它标记
                            var result = valid.IsValid(value, context);
                            if (result != ValidateResult.Success)
                            {
                                errors[member.MemberName] = CreateException(metadata, member, result.ErrorMessage);
                                flag = false;
                                break;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Configuration.DebugInfo("IsValid", ex);
                    throw;
                }
            }

            return flag;
        }

        public static bool IsValid<T, TResult>(T model, Expression<Func<T, TResult>> func, out ModelException error) 
        {
            throw new NotImplementedException("暂未实现此功能, 需要学习Lambda表达式目录树相关资料");
        }

        private static ModelException CreateException(
            ModelMetadata metadata,
            ModelMemberInfo prop,
            string error)
        {
            return new ModelException(prop, error, metadata);
        }
        #endregion

        private ModelExceptionCollection errors;
        private ModelExceptionCollection Errors { get { return this.errors; } }

        public object Input { get; set; }
        public Type Type { get; set; }

        public ObjectValidation()
        { 
        }

        public ObjectValidation(object input, Type type)
        {
            this.Input = input;
            this.Type = type;
        }

        bool IsValid()
        {
            return IsValid(this.Input, this.Type, out this.errors);
        }
    }
}
